/****************************************************************
 **版    本: 1.0
 **公    司: Lynkros Technologies (Beijing) Inc.
 **版    权: Lynkros
 **Date: 2019-11-20 15:44:36
 **LastEditTime: 2021-04-20 13:56:04
 **最后修改: Ray
 **描    述: 
 **FilePath: \Source\System\EditFrame.c
*****************************************************************/
/*        			TOS based applicationg, NAVIGATION			          			**
 **************************************************************************
 **                                                                        								**
 **          Copyright Lynkros Technologies INC.  2015-		               			**
 **                                                                        								**
 **************************************************************************
 **                                                                         								**
 **      	EditFrame.c:  C  文件                            	 						**
 **                                                                          							**
 **        	功能描述：编辑通信帧									**
 ** 				              												**
 **                                                                        								**
 **************************************************************************
 **                                                                        								**
 **    创建人：    		jiangzy                                                				**
 **    创建日期：   	2015-10-10                                                			**
 **    修改人:        		jiangzy                                                    				**
 **    修改日期：    	2015-10-10                                                			**
 **    修改内容:    														**
 **    版本：        		v_alfa_0.1_20151010_1                           				**
 **                                                                        								**
 *************************************************************************/
// #include "include.h"
#include "TypeDefine.h"
#include "global.h"
#include <string.h>
#include "my_uart.h"
#include "myDebug.h"

extern uint8_t uart_addr;      // 端口地址

uint16_t g_u16_frame_name = 1; // 帧名称

/****************************************************************************
 * 函数名称：
 * 功能描述：生成帧名称
 ** 输入：
 ** 输出：
 * 返回值：
 * 创建人：
 * 创建日期：
 * 备注：
 ****************************************************************************/
uint16_t GetFrameName(void)
{
    uint16_t tmpFrameName;
    tmpFrameName = g_u16_frame_name;
    g_u16_frame_name++;
    if (g_u16_frame_name > 60000)
    {
        g_u16_frame_name = 1;
    }
    // bkp_data_write(BKP_DATA_5, g_u16_frame_name); DOING:帧名称写入寄存器，没发现有啥作用
    return tmpFrameName;
}

//#define EnablePrint
/*********************************************************************************************************
 **----------------------------函数说明-------------------------------------------------------------------
 **函    数    名: EditFrame_VarDefine                                                                 **
 **类         型: int8                                                                                    **
 **入 口 参  数: uint32_t AppName;        // 所属事件名称                                                   **
 uint32_t TaskName;       // 变量名称或变量地址                                            **
 uint32_t EventName;      // 变量长度                                                     **
 uint16_t VarAmount：                                                                      **
 VarDescription_l_ST (*pVarDescription_l)[],    //VarDescription_l_ST数组的首地址     **
 uint8_t *Data;           // 变量数据的首地址                                             **
 **出 口 参  数: uint8_t  flag_process    处理成功标志，-1失败 其他值-发送任务编号                      **
 **功 能 描  述: 编辑变量定义帧                                                                            **
 *********************************************************************************************************/
uint16_t EditFrame_VarDefine(uint32_t AppName , uint32_t TaskName , uint32_t EventName , uint16_t VarAmount , VarDescription_l_ST (*pVarDescription_l)[] , DataDiscrp_ST (*pDataDiscrp_st)[] , uint8_t *Data)
{
    uint32_t i;
    uint8_t data_buf[1024] = {0x55, 0xFF, 0x0A, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
    FrameVarDefine_ST *pFrameVarDefine_st = (FrameVarDefine_ST *)&data_buf[2];
    uint16_t CRC_Check = 0;
    uint8_t *pDataAddr;      //传入的数据部分数据地址
    uint16_t DataLength = sizeof(VarFunc_Subjectto_ST) + 4;        // 通信帧长度
    VarDescription_ST *pVarDescription_tmp_st = NULL;
    uint32_t ByteLength;

    pFrameVarDefine_st->Var_Subjectto_st.AppName = AppName;
    pFrameVarDefine_st->Var_Subjectto_st.TaskName = TaskName;
    pFrameVarDefine_st->Var_Subjectto_st.EventName = EventName;
    pFrameVarDefine_st->VarAmount = VarAmount;

    //填充变量描述部分
    memcpy(pFrameVarDefine_st->VarDescription_l_st , pVarDescription_l , sizeof(VarDescription_l_ST) * VarAmount);
    DataLength += sizeof(VarDescription_l_ST) * VarAmount;

    pVarDescription_tmp_st = (VarDescription_ST *)&pFrameVarDefine_st->VarDescription_l_st[VarAmount];
    pDataAddr = Data;
    for(i = 0; i < VarAmount; i++)
    {
        memcpy(pVarDescription_tmp_st , (uint8_t *)&(*pDataDiscrp_st)[i] , sizeof(DataDiscrp_ST));
        ByteLength = pVarDescription_tmp_st->ByteLength;
        DataLength += sizeof(DataDiscrp_ST) + ByteLength;
        pVarDescription_tmp_st++;

        memcpy(pVarDescription_tmp_st , pDataAddr , ByteLength);
        pVarDescription_tmp_st = (VarDescription_ST *)((uint32_t)pVarDescription_tmp_st + ByteLength);
        pDataAddr += ByteLength;
    }
    pFrameVarDefine_st->FrameHead_st.DataLength = DataLength;
    pFrameVarDefine_st->FrameHead_st.FrameName = GetFrameName();
    DataLength += sizeof(FrameHead_ST);
    // 重新计算CRC校验
    pFrameVarDefine_st->FrameHead_st.DataCheck = 0;
    CRC_Check = CRCCheck((unsigned char *)pFrameVarDefine_st , DataLength);
    pFrameVarDefine_st->FrameHead_st.DataCheck = CRC_Check;
    DataLength += 2;
#ifdef EnablePrint
    for(i=0;i<DataLength;i++)
    {
        debug_printf("%02X ",data_buf[i]);
    }
    debug_printf("\n");
#endif
    // 写数据到fifo
    USART_Send(COM3 , data_buf , DataLength);

    return DataLength;
}


/**
 * 编辑一个App触发帧
 */
int EditFrameAppStart(InfAppStart_ST *pInfAppStart_st , VarDescription_l_ST *pVarDescription_l_st , uint8_t *pVarData, uint32_t COMx)
{
    uint8_t data_buf[1024] = {0x55, 0xFF, 0x10, 0x00, 0x06, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00};
    FrameAppStart_ST *pFrameAppStart_st = (FrameAppStart_ST *)&data_buf[2];
    uint16_t CRC_Check = 0;
    uint16_t DataLength;
    struct VarInput_ST VarInput_st;
    VarDescription_l_ST *pVarDescription_l_tmp_st;
    uint32_t pData_offset = 0;
    uint32_t i;

    pFrameAppStart_st->FrameHead_st.FrameType = 0x10;
    pFrameAppStart_st->FrameHead_st.SourceType = 0;
    pFrameAppStart_st->FrameHead_st.Keyword = 0xFFFFFFFF;
    pFrameAppStart_st->FrameHead_st.FrameName = GetFrameName();
    pFrameAppStart_st->FrameHead_st.FrameSeg_Total = 1;
    pFrameAppStart_st->FrameHead_st.FrameSeg_Num = 1;

    memcpy(&pFrameAppStart_st->InfAppStart_st , pInfAppStart_st , sizeof(InfAppStart_ST));
    DataLength = sizeof(FrameHead_ST) + sizeof(InfAppStart_ST);
    memcpy(&data_buf[DataLength + 2] , pVarDescription_l_st , sizeof(VarDescription_l_ST) * pInfAppStart_st->InitVarAmount);
    DataLength += sizeof(VarDescription_l_ST) * pInfAppStart_st->InitVarAmount;

    pVarDescription_l_tmp_st = pVarDescription_l_st;
    for(i = 0; i < pInfAppStart_st->InitVarAmount; i++)
    {
        VarInput_st.flag = 1;
        VarInput_st.length = pVarDescription_l_tmp_st->ByteLength;
        VarInput_st.step = 0x00010000;
        memcpy(&data_buf[DataLength + 2] , &VarInput_st , sizeof(struct VarInput_ST));
        DataLength += sizeof(struct VarInput_ST);
        memcpy(&data_buf[DataLength + 2] , (uint32_t *)&pVarData[pData_offset] , VarInput_st.length);
        DataLength += VarInput_st.length;
        pData_offset += VarInput_st.length;
        pVarDescription_l_tmp_st++;
    }
    pFrameAppStart_st->FrameHead_st.DataLength = DataLength - sizeof(FrameHead_ST);

    pFrameAppStart_st->FrameHead_st.DataCheck = 0;
    CRC_Check = CRCCheck((uint8_t *)pFrameAppStart_st , DataLength);
    pFrameAppStart_st->FrameHead_st.DataCheck = CRC_Check;
    DataLength += 2;
#ifdef EnablePrint
    for(i=0;i<DataLength;i++)
    {
        debug_printf("%02X ",data_buf[i]);
    }
    debug_printf("\n");
#endif
    // 将数据写入fifo
    USART_Send(COMx , data_buf , DataLength);

    return DataLength;
}

/**
 * 编辑ACK
 */
uint16_t EditFrameAck(uint16_t FrameName , uint16_t SegNum , uint32_t source)
{
    uint16_t DataLength = 6;
    uint16_t CRC_Check = 0;
    uint8_t data_buf[32] = {0x55, 0xFF, 0x01, 0x00, 0x06, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00};
    FrameACK_ST *pFrameACK_st = (FrameACK_ST *)&data_buf[2];

    pFrameACK_st->FrameSeg_Num_src = SegNum;
    pFrameACK_st->FrameName_src = FrameName;
    pFrameACK_st->FrameHead_st.FrameName = GetFrameName();
    DataLength += sizeof(FrameHead_ST);
    pFrameACK_st->FrameHead_st.DataCheck = 0;
    CRC_Check = CRCCheck((uint8_t *)pFrameACK_st , DataLength);
    pFrameACK_st->FrameHead_st.DataCheck = CRC_Check;
    DataLength += 2;

    // 将数据写入fifo
    USART_Send(source , data_buf , DataLength);

    return DataLength;
}

/****************************************************************
 **描  述: 
	编辑通信帧
    变量的名称可以用来识别读写
    目前只支持1个变量，多个变量不是不行，只是麻烦
 **输  入: 
	
 **输  出: 
	
 **返回值: 
	
 **Date: 2021-01-06 17:00:26
 **LastEditors: Ray
 **说  明: 
 **param {uint8_t} DstAddr    目标地址
 **param {VarDescription_ST} *pVarDescription_st    变量描述
 **param {uint8_t} *pVarData  变量数据
 **param {uint32_t} COMx  端口
*****************************************************************/
int EditFrameLocalVar(uint8_t DstAddr , VarDescription_ST *pVarDescription_st, uint8_t *pVarData, uint32_t COMx)
{
    App485Data_ST *pApp485Data_st = (App485Data_ST *)pVarData;
    struct RS485_VarName_ST *pName = (struct RS485_VarName_ST *)&pVarDescription_st->VarName;
    uint16_t DataLength = 0;
    uint16_t CRC_Check = 0;
    uint8_t data_buf[1024] = {0xFF, 0xFF, 0xFF, 0xFF, 0x55, 0xFF, 0x35, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x05};
    struct GeneralFrame_ST *pGeneralFrame_st = (struct GeneralFrame_ST *)&data_buf[FrameHeadFlagLength];
    struct LocalFrameDate_ST *pLocalFrameDate_st = (struct LocalFrameDate_ST *)pGeneralFrame_st->data;
    // int i;

    pLocalFrameDate_st->type = 6 - pApp485Data_st->FlagRW;
    pLocalFrameDate_st->var_amount = 1;
    // 从设备发送数据给主设备
    if(DstAddr == 0)
    {
        pLocalFrameDate_st->source = pName->COMAddr;
        pLocalFrameDate_st->dest = DstAddr;
    }
    // 主设备发数据给从设备
    else
    {
        pLocalFrameDate_st->source = 0;
        pLocalFrameDate_st->dest = DstAddr;
    }

    pLocalFrameDate_st->LocalVarDescription_st[0].var_name = pVarDescription_st->VarName;
    pLocalFrameDate_st->LocalVarDescription_st[0].var_length = pVarDescription_st->ByteLength;
    pLocalFrameDate_st->LocalVarDescription_st[0].VType_un.VarType = pVarDescription_st->VType_un.VarType;
    DataLength += 4 + sizeof(struct LocalVarDescription_ST);

    // 写数据
    if(pLocalFrameDate_st->type == emRS485Write)
    {
        // 赋值数据
        memcpy(&data_buf[FrameHeadFlagLength + sizeof(FrameHead_ST) + 4 + sizeof(struct LocalVarDescription_ST)] , pApp485Data_st->Data , pVarDescription_st->ByteLength);
        DataLength += pVarDescription_st->ByteLength;
    }
    // 帧首
    pGeneralFrame_st->FrameHead_st.DataLength = DataLength;
    pGeneralFrame_st->FrameHead_st.FrameName = GetFrameName();
    DataLength += sizeof(FrameHead_ST);
    // 校验
    pGeneralFrame_st->FrameHead_st.DataCheck = 0;
    CRC_Check = CRCCheck((uint8_t *)pGeneralFrame_st , DataLength);
    pGeneralFrame_st->FrameHead_st.DataCheck = CRC_Check;
    DataLength += FrameHeadFlagLength;
#ifdef EnablePrint
    for(i=0;i<DataLength;i++)
    {
        debug_printf("%02X ",data_buf[i]);
    }
    debug_printf("\n");
#endif
    // 将数据写入fifo
    USART_Send(COMx , data_buf , DataLength);

    return DataLength;
}

/****************************************************************
 **描  述: 
	多变量写
 **输  入: 
	
 **输  出: 
	
 **返回值: 
	
 **Date: 2021-01-06 16:58:36
 **LastEditors: Ray
 **说  明: 主要是为从设备发送数据使用的
 **param {VarDescription_ST} *pVarDescription_st
 **param {uint8_t} *pVarData
 **param {uint32_t} VarAmount
 **param {uint32_t} COMx
*****************************************************************/
int EditFrameLocalVar4(VarDescription_ST *pVarDescription_st, uint8_t *pVarData, uint32_t VarAmount, uint32_t COMx)
{
    VarDescription_ST *pVarDescription_st_temp = pVarDescription_st;
    uint16_t DataLength = 4;
    uint16_t CRC_Check = 0;
    uint8_t data_buf[1024] = {0xFF, 0xFF, 0xFF, 0xFF, 0x55, 0xFF, 0x35, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x05};
    struct GeneralFrame_ST *pGeneralFrame_st = (struct GeneralFrame_ST *)&data_buf[FrameHeadFlagLength];
    struct LocalFrameDate_ST *pLocalFrameDate_st = (struct LocalFrameDate_ST *)pGeneralFrame_st->data;
    int i;

    pLocalFrameDate_st->type = emRS485Write;
    pLocalFrameDate_st->var_amount = VarAmount;
    pLocalFrameDate_st->source = uart_addr;
    pLocalFrameDate_st->dest = 0;

    for(i = 0; i < VarAmount; i++)
    {
        pLocalFrameDate_st->LocalVarDescription_st[i].var_name = pVarDescription_st_temp->VarName;
        pLocalFrameDate_st->LocalVarDescription_st[i].var_length = pVarDescription_st_temp->ByteLength;
        pLocalFrameDate_st->LocalVarDescription_st[i].VType_un.VarType = pVarDescription_st_temp->VType_un.VarType;
        DataLength += sizeof(struct LocalVarDescription_ST);
        pVarDescription_st_temp ++;
    }

    pVarDescription_st_temp = pVarDescription_st;
    for(i = 0; i < VarAmount; i++)
    {
        // 赋值数据
        memcpy(&data_buf[FrameHeadFlagLength + sizeof(FrameHead_ST) + DataLength] , pVarData , pVarDescription_st_temp->ByteLength);
        DataLength += pVarDescription_st_temp->ByteLength;
        pVarData += pVarDescription_st_temp->ByteLength;
        pVarDescription_st_temp++;
    }

    // 帧首
    pGeneralFrame_st->FrameHead_st.DataLength = DataLength;
    pGeneralFrame_st->FrameHead_st.FrameName = GetFrameName();
    DataLength += sizeof(FrameHead_ST);
    // 校验
    pGeneralFrame_st->FrameHead_st.DataCheck = 0;
    CRC_Check = CRCCheck((uint8_t *)pGeneralFrame_st , DataLength);
    pGeneralFrame_st->FrameHead_st.DataCheck = CRC_Check;
    DataLength += FrameHeadFlagLength;
#ifdef EnablePrint
    for(i=0;i<DataLength;i++)
    {
        printf("%02X ",data_buf[i]);
    }
    printf("\n");
#endif
    // 将数据写入fifo
    USART_Send(COMx , data_buf , DataLength);
    
    return DataLength;
}

//地址申请专用
int EditFrameLocalVar5(VarDescription_ST *pVarDescription_st, uint8_t *pVarData, uint32_t VarAmount, uint32_t COMx)
{
	struct RS485_VarName_ST *pName = (struct RS485_VarName_ST *)&pVarDescription_st->VarName;
    VarDescription_ST *pVarDescription_st_temp = pVarDescription_st;
    uint16_t DataLength = 4;
    uint16_t CRC_Check = 0;
    uint8_t data_buf[1024] = {0xFF, 0xFF, 0xFF, 0xFF, 0x55, 0xFF, 0x35, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x05};
    struct GeneralFrame_ST *pGeneralFrame_st = (struct GeneralFrame_ST *)&data_buf[FrameHeadFlagLength];
    struct LocalFrameDate_ST *pLocalFrameDate_st = (struct LocalFrameDate_ST *)pGeneralFrame_st->data;
    int i;

    pLocalFrameDate_st->type = emRS485Write;
    pLocalFrameDate_st->var_amount = VarAmount;
    pLocalFrameDate_st->source = pName->COMAddr;
    pLocalFrameDate_st->dest = 0;

    for(i = 0; i < VarAmount; i++)
    {
        pLocalFrameDate_st->LocalVarDescription_st[i].var_name = pVarDescription_st_temp->VarName;
        pLocalFrameDate_st->LocalVarDescription_st[i].var_length = pVarDescription_st_temp->ByteLength;
        pLocalFrameDate_st->LocalVarDescription_st[i].VType_un.VarType = pVarDescription_st_temp->VType_un.VarType;
        DataLength += sizeof(struct LocalVarDescription_ST);
        pVarDescription_st_temp ++;
    }

    pVarDescription_st_temp = pVarDescription_st;
    for(i = 0; i < VarAmount; i++)
    {
        // 赋值数据
        memcpy(&data_buf[FrameHeadFlagLength + sizeof(FrameHead_ST) + DataLength] , pVarData+4, pVarDescription_st_temp->ByteLength);
        DataLength += pVarDescription_st_temp->ByteLength;
        pVarData += pVarDescription_st_temp->ByteLength;
        pVarDescription_st_temp++;
    }

    // 帧首
    pGeneralFrame_st->FrameHead_st.DataLength = DataLength;
    pGeneralFrame_st->FrameHead_st.FrameName = GetFrameName();
    DataLength += sizeof(FrameHead_ST);
    // 校验
    pGeneralFrame_st->FrameHead_st.DataCheck = 0;
    CRC_Check = CRCCheck((uint8_t *)pGeneralFrame_st , DataLength);
    pGeneralFrame_st->FrameHead_st.DataCheck = CRC_Check;
    DataLength += FrameHeadFlagLength;
#ifdef EnablePrint
    for(i=0;i<DataLength;i++)
    {
        MY_DEBUG("%02X ",data_buf[i]);
    }
    MY_DEBUG("\n");
#endif
    // 将数据写入fifo
    USART_Send(COMx , data_buf , DataLength);

    return DataLength;
}